﻿using System;
using System.IO;
using System.Security.Principal;
using System.Web;
using System.Linq;
using System.Web.Mvc;

namespace EditRegion.MVC
{
    /// <summary>
    /// Generates the markup required for displaying the Editor or Content depending on user permissions. This
    /// is also the class implements does the fluent api interface.
    /// </summary>
    public class EditRegionMarkUp : IHideObjectMembers
    {
        #region Private Variables
        private string markUp;
        private bool isEditable;
        private bool doNotEncode;
        private string id;
        private string content;
        private string labelText;
        private readonly IPrincipal user;
        private readonly HtmlServer htmlServer;
        private readonly HtmlHelper htmlHelper; 
        #endregion

        #region Private Properties
        private string Username
        {
            get
            {
                return user.Identity.Name;
            }
        }

        #endregion

        #region Internal Methods
        internal EditRegionMarkUp(HtmlHelper htmlHelper)
        {
            htmlServer = new HtmlServer();
            this.htmlHelper = htmlHelper;
            user = HttpContext.Current.User;
        }

        /// <summary>
        /// This Constructor is used for Unit Testing
        /// </summary>
        internal EditRegionMarkUp(HtmlHelper htmlHelper, FileSystemInfo contentFile, IPrincipal user)
        {
            htmlServer = new HtmlServer(contentFile);
            this.htmlHelper = htmlHelper;
            this.user = user;
        }

        internal EditRegionMarkUp GetEditRegion(string contentId)
        {
            id = contentId;
            content = htmlServer.GetContent(contentId);
            markUp = content;
            return this;
        } 
        #endregion

        #region Authorization
        public EditRegionMarkUp EditableForRole(string role)
        {
            if (user.IsInRole(role))
            {
                isEditable = true;
            }

            return this;
        }

        public EditRegionMarkUp EditableForRoles(string[] roles)
        {
            foreach (var role in roles)
            {
                if (!user.IsInRole(role)) {continue;}
                isEditable = true;
                break;
            }

            return this;
        }

        public EditRegionMarkUp EditableForUser(string userName)
        {
            if(Username.Equals(userName, StringComparison.InvariantCultureIgnoreCase))
            {
                isEditable = true;
            }

            return this;
        }

        public EditRegionMarkUp EditableForUsers(string[] users)
        {
            if (users.Where(u => u.Equals(Username, StringComparison.InvariantCultureIgnoreCase)).Count() > 0)
            {
                isEditable = true;
            }

            return this;
        } 
        #endregion

        public EditRegionMarkUp Label(string label)
        {
            labelText = label;
            return this;
        }

        public EditRegionMarkUp DoNotEncode()
        {
            doNotEncode = true;
            return this;
        }

        public override string ToString()
        {
            if (!isEditable && !doNotEncode)
            {
                content = htmlHelper.Encode(content);
            }

            markUp = isEditable 
                ? HtmlServer.GetEditor(id, content) 
                : content;
            
            if(isEditable)
            {
                AddLabel();
            }

            return markUp;
        }

        private void AddLabel()
        {
            if(string.IsNullOrEmpty(labelText))
            {
                return;
            }

            markUp = "<label for=\"" + id + "\">" + labelText + "</label>" + markUp;
        }
    }
}
